'''
Created on 2012-3-28下午8:38:29

@author: yasenagat
@email:   yasenagat@gmail.com

'''
#函数的参数可以有默认值
def add(x, y=4):
    return x + y;


ret = add(1, 2);
print(ret)
#使用默认值
ret = add(0)
print(ret)
#使用关键字的方式传值，没有参数的顺序限制
ret = add(y=9, x=4)
print(ret)

#给最后一个参数名加上*,函数就可以接收任意多个参数,多个参数以元组的形式接收
def p(x, *args):
    #args是元组
    print(args)
    
p(1, 2, 2, 3, 'a')

#*args表示任何多个无名参数，它是一个tuple；
#**kwargs表示关键字参数，它是一个 dict。a=1,b=2这种方式传递参数
#并且同时使用*args和**kwargs时，必须*args参数列要在**kwargs前
def t(*args, **kwargs):
    
    print(args, kwargs)
    
t('a', 'b', a=1, b=3)



#方法中还可以定义方法，是不是很蛋疼，这种语法！！！

#强大的过了分了，也不是个好事,方法内要点用外层方法的属性要加nonlocal
def t1(n):
    
    pix = 1.2
    
    def t2():
        return n * pix
    def t3():
        return n / pix
    
    if n % 2 == 0:
        return t3()
    else :
        return t2()
        
print(t1(3))

#没搞懂nonlocal什么意思
def tt(n):
    m = n
    
    def t2():
        print(m)
    
    t2()
    
tt(22)


#函数是第一类对象,函数作为参数传递给另一个函数，你敢说不神奇吗!
def call(func):
    #传递的参数是一个函数
    return func()

def say():
    return 'Hi'

print(call(say))


#函数还可以作为返回值，有木有，真是一个神奇的语言

def c(str):
    
    def get():
        print(str)
        
    return get  #这个是返回get方法，但是get方法还没有被执行
#    return get() #这个是返回get()方法的返回值

#返回的是一个方法
get1 = c('哈哈')
#查看闭包
print(get1.__closure__) #(<cell at 0x00C77130: str object at 0x00C54FC0>,)
print(get1.__closure__[0].cell_contents) #哈哈
get1()

#返回的是一个方法，两个方法相同，不过带着的参数不同
get2 = c('嘿嘿')
get2()

#get1和get2是get方法的两个版本


#闭包，是不是这么个意思
def countdown(n):
    #目测闭包是这样的，
    #函数内包含函数，传递外层的函数，在内层函数中使用，不在被外面调用
    #最关键的是，函数返回的函数内的一个函数，这个内部函数把参数封闭在的内部函数内
    
    def next():
        nonlocal n
        r = n
        n -= 1
        return r
    
    return next

#把10这个参数，封闭在next这个函数内部
next = countdown(10)

#测试闭包
while True:
    v = next()
    print(v)#0:false ;1:true
    if not v : break

#简单函数的写法，超级简单,用途指定短小的回调函数,后面必须是表达式
#lambda 参数一，参数二:返回值或者其他操作，然后赋值给a，a就是函数了，调用a(参数一，参数二)就可以了
a = lambda x, y:print('返回值是：', x + y)

a(2, 3)

#
b = lambda x,y : x-y

# 三元表达式 b if a else c
c = lambda x,y:1 if x>y  else -1

print('结果',c(1,3))

#函数也有文档字符串
def foo():
    '''函数的文档'''
    pass

print('foo的解释:',foo.__doc__)


#函数还能有属性，真是奇迹了,函数的属性保存在f.__dict__中，key value
def f():
    pass

f.name ='f'
f.age = '300'

print(f.__dict__)
print(f.name)

s = 'print(1)'
exec(s)
#将语句编译为代码，然后执行
c = compile(s,'','exec')
exec(c)

#compile(str,filename,kind)
#kind : single一条语句，exec一组语句，eval表达式

x = 1
y = 2
s2 = "3*x + 4*y"
print(exec(s2))
c2 = compile(s2,'','eval')
result = eval(c2)
print(result)